﻿using Mapster;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Shipeng.Util;
using SqlSugar;
using Sharpen;
using Globalization=System.Globalization;
using System.ComponentModel.DataAnnotations;
using System.Linq.Expressions;
using System.Text;
using YNTK.Common.Const;
using YNTK.Common.Enum;
using YNTK.Common.Filter;
using YNTK.Data.MongoDB.Repositorie;
using YNTK.DataEncryption;
using YNTK.Dependency;
using YNTK.DynamicApiController;
using YNTK.Employees.Entitys.Dto;
using YNTK.Employees.Entitys.Entity;
using YNTK.Employees.Interface;
using YNTK.EventBridge;
using YNTK.FriendlyException;
using YNTK.LinqBuilder;
using YNTK.Mapster;
using YNTK.System.Entitys.Dto.Common;
using YNTK.System.Entitys.Permission;
using YNTK.System.Interfaces.Common;
using YNTK.System.Interfaces.Permission;
using MongoDB.Driver;
using Yitter.IdGenerator;

namespace YNTK.Employees
{
    /// <summary>
    /// 员工服务的实现
    /// 版 本：V1.0.0
    /// 版 权：云南通科科技有限公司（https://www.yntkkj.com）
    /// 作 者：李仕鹏
    /// 日 期：2022-11-02
    /// </summary>
    [ApiDescriptionSettings(Tag = "员工服务", Name = "Employees", Order = 784)]
    [Route("api/[controller]")]
    public class EmployeesService: IEmployeesService, IDynamicApiController, ITransient
    {
        private readonly ISqlSugarRepository<EmployeesEntity> _employeesRepository;//员工仓储
        private readonly IMongoDBRepository<EmployeesEntity> _employeesMongoDbRepository;//员工mongodb仓储
        private readonly ISqlSugarRepository<EducationExperiencesEntity> _educationRepository;//员工教育经历仓储
        private readonly IMongoDBRepository<EducationExperiencesEntity> _educationMongoDbRepository;//员工教育经历mongodb仓储
        private readonly ISqlSugarRepository<FamilyMembersEntity> _familyRepository;//员工家庭成员仓储
        private readonly IMongoDBRepository<FamilyMembersEntity> _familyMongoDbRepository;//员工家庭成员mongodb仓储
        private readonly ISqlSugarRepository<WorkExperiencesEntity> _workRepository;//员工工作经历仓储
        private readonly IMongoDBRepository<WorkExperiencesEntity> _workMongoDbRepository;//员工工作经历mongodb仓储
        private readonly ISqlSugarRepository<TechnicalCertificateEntity> _certificateRepository;//员工技术职称证书仓储
        private readonly IMongoDBRepository<TechnicalCertificateEntity> _certificateMongoDbRepository;//员工技术职称证书mongodb仓储

        private readonly IOrganizeService _organizeService;//组织服务
        private readonly IMechanismService _mechanismService;//机构服务
        private readonly ITkRoleService _tkRoleService;//角色服务
        private readonly IFileService _fileService;//文件服务
        private readonly ITkUsersService _tkUsersService;//用户服务
        private readonly HttpContext _httpContext;

        private readonly string _employees = "employees_rosters";//mongodb中员工数据集名称
        private readonly string _educations = "employees_educationexperiences";//mongodb中员工教育经历数据集名称
        private readonly string _familymembers = "employees_familymembers";//mongodb中员工家庭成员数据集名称
        private readonly string _works = "employees_workexperiences";//mongodb中员工工作经历数据集名称
        private readonly string _technicalcertificates = "employees_technicalcertificates";//mongodb中员工技术职称证书数据集名称

        /// <summary>
        /// 构造方法依赖注入
        /// </summary>
        /// <param name="employeesRepository">员工仓储</param>
        /// <param name="employeesMongoDbRepository">员工mongodb仓储</param>
        /// <param name="educationRepository">员工教育经历仓储</param>
        /// <param name="educationMongoDbRepository">员工教育经历mongodb仓储</param>
        /// <<param name="familyRepository">员工家庭成员仓储</param>
        /// <param name="familyMongoDbRepository">员工家庭成员mongodb仓储</param>
        /// <param name="workRepository">员工工作经历仓储</param>
        /// <param name="workMongoDbRepository">员工工作经历mongodb仓储</param>
        /// <param name="certificateRepository">员工技术职称证书仓储</param>
        /// <param name="certificateMongoDbRepository">员工技术职称证书mongodb仓储</param>
        /// <param name="organizeService">组织服务</param>
        /// <param name="mechanismService">机构服务</param>
        /// <param name="tkRoleService">角色服务</param>
        /// <param name="fileService">文件服务</param>
        /// <param name="tkUsersService">用户服务</param>
        public EmployeesService(ISqlSugarRepository<EmployeesEntity> employeesRepository,
            IMongoDBRepository<EmployeesEntity> employeesMongoDbRepository,
            ISqlSugarRepository<EducationExperiencesEntity> educationRepository,
            IMongoDBRepository<EducationExperiencesEntity> educationMongoDbRepository,
            ISqlSugarRepository<FamilyMembersEntity> familyRepository,
            IMongoDBRepository<FamilyMembersEntity> familyMongoDbRepository,
            ISqlSugarRepository<WorkExperiencesEntity> workRepository,
            IMongoDBRepository<WorkExperiencesEntity> workMongoDbRepository,
            ISqlSugarRepository<TechnicalCertificateEntity> certificateRepository,
            IMongoDBRepository<TechnicalCertificateEntity> certificateMongoDbRepository,
            IOrganizeService organizeService, IMechanismService mechanismService,
            ITkRoleService tkRoleService, IFileService fileService,
            ITkUsersService tkUsersService)
        {
            _employeesRepository = employeesRepository;
            _employeesMongoDbRepository = employeesMongoDbRepository;
            _educationRepository = educationRepository;
            _educationMongoDbRepository = educationMongoDbRepository;
            _familyRepository = familyRepository;
            _familyMongoDbRepository = familyMongoDbRepository;
            _workRepository = workRepository;
            _workMongoDbRepository = workMongoDbRepository;
            _certificateRepository = certificateRepository;
            _certificateMongoDbRepository = certificateMongoDbRepository;

            _organizeService = organizeService;
            _mechanismService = mechanismService;
            _tkRoleService = tkRoleService;
            _fileService = fileService;
            _tkUsersService = tkUsersService;
            _httpContext = App.HttpContext;
        }

        #region 基础数据
        /// <summary>
        /// 获取员工状态类型
        /// </summary>
        /// <returns></returns>
        [HttpGet("employeestate")]
        public TkResult<List<EnumListDto>> GetEmployeeStateList()
        {
            Dictionary<int, string> dic = EnumHelper.EnumToDic<EmployeeStateEnum>();
            var result = new List<EnumListDto>();
            foreach (KeyValuePair<int, string> kv in dic)
            {
                result.Add(new EnumListDto { Id = kv.Key.ToStr(), Value = kv.Key, Description = kv.Value });
            }
            return TkResult<List<EnumListDto>>.Success(result);
        }

        /// <summary>
        /// 获取劳动关系类型
        /// </summary>
        /// <returns></returns>
        [HttpGet("laborrelations")]
        public TkResult<List<EnumListDto>> GetLaborRelationsList()
        {
            Dictionary<int, string> dic = EnumHelper.EnumToDic<LaborRelationsEnum>();
            var result = new List<EnumListDto>();
            foreach (KeyValuePair<int, string> kv in dic)
            {
                result.Add(new EnumListDto { Id = kv.Key.ToStr(), Value = kv.Key, Description = kv.Value });
            }
            return TkResult<List<EnumListDto>>.Success(result);
        }

        /// <summary>
        /// 获取薪酬方式类型
        /// </summary>
        /// <returns></returns>
        [HttpGet("payway")]
        public TkResult<List<EnumListDto>> GetPayWayList()
        {
            Dictionary<int, string> dic = EnumHelper.EnumToDic<PayWayEnum>();
            var result = new List<EnumListDto>();
            foreach (KeyValuePair<int, string> kv in dic)
            {
                result.Add(new EnumListDto { Id = kv.Key.ToStr(), Value = kv.Key, Description = kv.Value });
            }
            return TkResult<List<EnumListDto>>.Success(result);
        }

        /// <summary>
        /// 获取性别类型
        /// </summary>
        /// <returns></returns>
        [HttpGet("sex")]
        public TkResult<List<EnumListDto>> GetSexList()
        {
            Dictionary<int, string> dic = EnumHelper.EnumToDic<SexEnum>();
            var result = new List<EnumListDto>();
            foreach (KeyValuePair<int, string> kv in dic)
            {
                result.Add(new EnumListDto { Id = kv.Key.ToStr(), Value = kv.Key, Description = kv.Value });
            }
            return TkResult<List<EnumListDto>>.Success(result);
        }

        /// <summary>
        /// 获取婚姻状态类型
        /// </summary>
        /// <returns></returns>
        [HttpGet("maritalstate")]
        public TkResult<List<EnumListDto>> GetMaritalStateList()
        {
            Dictionary<int, string> dic = EnumHelper.EnumToDic<MaritalStateEnum>();
            var result = new List<EnumListDto>();
            foreach (KeyValuePair<int, string> kv in dic)
            {
                result.Add(new EnumListDto { Id = kv.Key.ToStr(), Value = kv.Key, Description = kv.Value });
            }
            return TkResult<List<EnumListDto>>.Success(result);
        }

        /// <summary>
        /// 获取政治面貌类型
        /// </summary>
        /// <returns></returns>
        [HttpGet("politicallandscape")]
        public TkResult<List<EnumListDto>> GetPoliticalLandscapeList()
        {
            Dictionary<int, string> dic = EnumHelper.EnumToDic<PoliticalLandscapeEnum>();
            var result = new List<EnumListDto>();
            foreach (KeyValuePair<int, string> kv in dic)
            {
                result.Add(new EnumListDto { Id = kv.Key.ToStr(), Value = kv.Key, Description = kv.Value });
            }
            return TkResult<List<EnumListDto>>.Success(result);
        }

        /// <summary>
        /// 获取户口性质类型
        /// </summary>
        /// <returns></returns>
        [HttpGet("householdregister")]
        public TkResult<List<EnumListDto>> GetHouseholdRegisterList()
        {
            Dictionary<int, string> dic = EnumHelper.EnumToDic<HouseholdRegisterEnum>();
            var result = new List<EnumListDto>();
            foreach (KeyValuePair<int, string> kv in dic)
            {
                result.Add(new EnumListDto { Id = kv.Key.ToStr(), Value = kv.Key, Description = kv.Value });
            }
            return TkResult<List<EnumListDto>>.Success(result);
        }

        /// <summary>
        /// 获取学历类型
        /// </summary>
        /// <returns></returns>
        [HttpGet("education")]
        public TkResult<List<EnumListDto>> GetEducationList()
        {
            Dictionary<int, string> dic = EnumHelper.EnumToDic<EducationEnum>();
            var result = new List<EnumListDto>();
            foreach (KeyValuePair<int, string> kv in dic)
            {
                result.Add(new EnumListDto { Id = kv.Key.ToStr(), Value = kv.Key, Description = kv.Value });
            }
            return TkResult<List<EnumListDto>>.Success(result);
        }

        /// <summary>
        /// 获取学位类型
        /// </summary>
        /// <returns></returns>
        [HttpGet("degree")]
        public TkResult<List<EnumListDto>> GetDegreeList()
        {
            Dictionary<int, string> dic = EnumHelper.EnumToDic<DegreeEnum>();
            var result = new List<EnumListDto>();
            foreach (KeyValuePair<int, string> kv in dic)
            {
                result.Add(new EnumListDto { Id = kv.Key.ToStr(), Value = kv.Key, Description = kv.Value });
            }
            return TkResult<List<EnumListDto>>.Success(result);
        }

        /// <summary>
        /// 获取在岗情况
        /// </summary>
        /// <returns></returns>
        [HttpGet("dutystates")]
        public TkResult<List<EnumListDto>> GetDutyStateList()
        {
            Dictionary<int, string> dic = EnumHelper.EnumToDic<DutyStateEnum>();
            var result = new List<EnumListDto>();
            foreach (KeyValuePair<int, string> kv in dic)
            {
                result.Add(new EnumListDto { Id = kv.Key.ToStr(), Value = kv.Key, Description = kv.Value });
            }
            return TkResult<List<EnumListDto>>.Success(result);
        }
        #endregion

        #region 员工
        /// <summary>
        /// 分页获取员工数据
        /// </summary>
        /// <param name="query">查询员工请求模型</param>
        /// <returns></returns>
        [HttpPost("gets/employees")]
        public async Task<TkPageResult<EmployeeListDto>> Gets([FromBody] QueryEmployeeFilterRequestModel query)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;

                #region 拼接查询条件
                Expression<Func<EmployeesEntity, bool>> where = m => m.OrganizeId == organizeId;
                if (!string.IsNullOrWhiteSpace(query.mechanismId))
                {
                    string queryMechanismId = await _mechanismService.GetIdAsync(query.mechanismId, organizeId);
                    where = where.And(m => m.MechanismId == queryMechanismId);
                }
                if (!string.IsNullOrWhiteSpace(query.roleId)) where = where.And(m => m.RoleId == query.roleId);
                if (query.laborRelations != null) where = where.And(m=>m.LaborRelations==query.laborRelations.GetHashCode());
                if (query.sex != null) where = where.And(m => m.Sex == query.sex.GetHashCode());
                if (query.payWay != null) where = where.And(m => m.PayWay == query.payWay.GetHashCode());
                if (query.education != null) where = where.And(m => m.Education == query.education.GetHashCode());
                if (query.maritalState != null) where = where.And(m => m.MaritalState == query.maritalState.GetHashCode());
                if (query.politicalLandscape != null) where = where.And(m => m.PoliticalLandscape == query.politicalLandscape.GetHashCode());
                if (query.householdRegister != null) where = where.And(m => m.HouseholdRegister == query.householdRegister.GetHashCode());
                if (query.temporaryWork != null) where = where.And(m=>m.TemporaryWork==query.temporaryWork);
                if (!string.IsNullOrWhiteSpace(query.keyword))
                    where = where.And(m=>m.Account.Contains(query.keyword) || m.RealName.Contains(query.keyword) 
                    || m.Code.Contains(query.keyword) || m.CertificatesNumber.Contains(query.keyword) ||
                    m.MobilePhone.Contains(query.keyword) || m.TelePhone.Contains(query.keyword) ||
                    m.Landline.Contains(query.keyword) || m.Email.Contains(query.keyword) ||
                    m.Nation.Contains(query.keyword) || m.NativePlace.Contains(query.keyword) ||
                    m.DomicileAddress.Contains(query.keyword) || m.PermanentAddress.Contains(query.keyword) ||
                    m.WagesCardNumber.Contains(query.keyword) || m.BankDeposit.Contains(query.keyword) ||
                    m.Branches.Contains(query.keyword));
                #endregion

                var pageList = new SqlSugarPagedList<EmployeeListDto>();

                #region 先从mongodb中获取员工数据
                //排序生成器
                var builderSort = Builders<EmployeesEntity>.Sort;
                //排序约束   Ascending 正序    Descending 倒序
                var sort = builderSort.Descending(r => r.CreatorTime).Descending(r => r.LastModifyTime);
                //Item1.结果集 Item2.总条数 Item3.总页数
                (List<EmployeesEntity>, int, int) result =
                    await _employeesMongoDbRepository.GetListAsync(_employees,
                    where, query.currentPage, query.pageSize, null, sort);
                pageList.list = result.Item1.Adapt<List<EmployeeListDto>>();
                pageList.pagination = new PagedModel()
                {
                    PageIndex = query.currentPage,
                    PageSize = query.pageSize,
                    Total = result.Item2,
                    PageCount = result.Item3
                };
                #endregion

                if (!pageList.list.Any())
                {
                    #region 再从sqlserver中获取员工数据
                    var sqlResult = await _employeesRepository.Entities.Where(where)
                        .OrderBy(r => r.CreatorTime, OrderByType.Desc)
                        .OrderBy(r => r.LastModifyTime, OrderByType.Desc)
                        .ToPagedListAsync(query.currentPage, query.pageSize);
                    pageList.list = sqlResult.list.Adapt<List<EmployeeListDto>>();
                    pageList.pagination = sqlResult.pagination;
                    #endregion
                }

                #region 处理员工返回数据
                if (pageList.list.Any())
                {
                    var orgIds = pageList.list.Select(r => r.organizeId).Distinct().ToList();
                    var orgs = await _organizeService.GetOrganizeListByIds(orgIds);
                    var mechanismIds = pageList.list.Where(r => !string.IsNullOrWhiteSpace(r.mechanismId))
                         ?.Select(r => r.mechanismId.Split(',').ToList())
                         ?.SelectMany(r => r).Distinct().ToList();
                    var mechanisms = await _mechanismService.GetMechanismListAsync("", mechanismIds);
                    var roleIds = pageList.list.Where(r => !string.IsNullOrWhiteSpace(r.roleId))
                        ?.Select(r => r.roleId).Distinct().ToList();
                    var roles = await _tkRoleService.GetTkRoleListByIdsAsync(roleIds);
                    pageList.list.ForEach(employee =>
                    {
                        if (!string.IsNullOrWhiteSpace(employee.organizeId))
                            employee.organizeName = orgs?.FirstOrDefault(r => r.Id == employee.organizeId)?.FullName;
                        if (!string.IsNullOrWhiteSpace(employee.mechanismId))
                        {
                            employee.mechanismName = string.Join('/', mechanisms
                                ?.Where(r => employee.mechanismId.Split(',').ToList().Contains(r.Id))
                                ?.Select(r => r.Name)?.ToList()).Split('/').Last();
                        }
                        if (!string.IsNullOrWhiteSpace(employee.roleId))
                            employee.roleName = roles?.FirstOrDefault(r => r.Id == employee.roleId)?.Name;
                        if (employee.dutyState == null) employee.dutyState = 0;//在岗情况(0.正常 1.请假 2.出差)
                        employee.dutyStateText = employee.dutyState == null ? "" :
                        EnumHelper.GetEnumDescriptionString((int)employee.dutyState, typeof(DutyStateEnum));
                        employee.sexText = employee.sex == null ? "" :
                        EnumHelper.GetEnumDescriptionString((int)employee.sex, typeof(SexEnum));
                        employee.educationText = employee.education == null ? "" :
                        EnumHelper.GetEnumDescriptionString((int)employee.education, typeof(EducationEnum));
                        employee.laborRelationsText = employee.laborRelations == null ? "" :
                        EnumHelper.GetEnumDescriptionString((int)employee.laborRelations, typeof(LaborRelationsEnum));
                        employee.stateText = employee.state == null ? "" :
                        EnumHelper.GetEnumDescriptionString((int)employee.state, typeof(EmployeeStateEnum));
                        employee.payWayText = employee.payWay == null ? "" :
                        EnumHelper.GetEnumDescriptionString((int)employee.payWay, typeof(PayWayEnum));
                        employee.maritalStateText = employee.maritalState == null ? "" :
                        EnumHelper.GetEnumDescriptionString((int)employee.maritalState, typeof(MaritalStateEnum));
                        employee.politicalLandscapeText = employee.politicalLandscape == null ? "" :
                        EnumHelper.GetEnumDescriptionString((int)employee.politicalLandscape, typeof(PoliticalLandscapeEnum));
                        employee.householdRegisterText = employee.householdRegister == null ? "" :
                        EnumHelper.GetEnumDescriptionString((int)employee.householdRegister, typeof(HouseholdRegisterEnum));
                        if (!string.IsNullOrWhiteSpace(employee.curriculumVitae))
                            employee.curriculumVitaeFileName = employee.curriculumVitae.Split("{@yntk@}")[1];
                        if (employee.dateEntry != null)
                        {
                            //计算工龄
                            (int year, int month, int days, string age) = CalculateWorkingAge((DateTime)employee.dateEntry);
                            employee.workingAge = age;
                        }
                        if (employee.dateBirth != null)
                            employee.age = GetAgeByBirthdate((DateTime)employee.dateBirth) + "岁";
                    });
                }
                #endregion

                return TkPageResult<EmployeeListDto>.Success(pageList);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"分页获取员工数据发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 获取员工基本信息
        /// </summary>
        /// <param name="id">员工id</param>
        /// <returns></returns>
        [HttpGet("get/{id}")]
        public async Task<TkResult<EmployeesInfoDto>> Get([Required] string id)
        {
            try
            {
                var employee = new EmployeesInfoDto();
                var entity = await GetEmployeesInfoAsync(r => r.Id == id);
                if(entity==null)
                {
                    var userInfo= await _tkUsersService.GetUserInfoByUserId(id);
                    _ = userInfo ?? throw YNTKException.Oh(ErrorCode.Employee0001);
                    employee = userInfo.Adapt<EmployeesInfoDto>();
                }
                else employee = entity.Adapt<EmployeesInfoDto>();
                if (employee != null)
                {
                    if (!string.IsNullOrWhiteSpace(employee.organizeId))
                        employee.organizeName = (await _organizeService.GetOrganizeListByIds
                            (new List<string>() { employee.organizeId }))?[0].FullName;
                    if (!string.IsNullOrWhiteSpace(employee.mechanismId) && employee.mechanismId != "jg000000")
                    {
                        var mechanismIds = employee.mechanismId.Split(',').ToList();
                        employee.mechanismName = string.Join('/', (await _mechanismService.GetMechanismListAsync("", mechanismIds))
                            ?.Select(r => r.Name)?.ToList()).Split('/').Last();                       
                    }
                    if (!string.IsNullOrWhiteSpace(employee.roleId))
                        employee.roleName = (await _tkRoleService.GetTkRoleListByIdsAsync
                            (new List<string>() { employee.roleId }))?[0].Name;
                    if (employee.dutyState == null) employee.dutyState = 0;//在岗情况(0.正常 1.请假 2.出差)
                    employee.dutyStateText = employee.dutyState == null ? "" :
                    EnumHelper.GetEnumDescriptionString((int)employee.dutyState, typeof(DutyStateEnum));
                    employee.sexText = employee.sex == null ? "" :
                    EnumHelper.GetEnumDescriptionString((int)employee.sex, typeof(SexEnum));
                    employee.educationText = employee.education == null ? "" :
                    EnumHelper.GetEnumDescriptionString((int)employee.education, typeof(EducationEnum));
                    employee.laborRelationsText = employee.laborRelations == null ? "" :
                    EnumHelper.GetEnumDescriptionString((int)employee.laborRelations, typeof(LaborRelationsEnum));
                    employee.stateText = employee.state == null ? "" :
                    EnumHelper.GetEnumDescriptionString((int)employee.state, typeof(EmployeeStateEnum));
                    employee.payWayText = employee.payWay == null ? "" :
                    EnumHelper.GetEnumDescriptionString((int)employee.payWay, typeof(PayWayEnum));
                    employee.maritalStateText = employee.maritalState == null ? "" :
                    EnumHelper.GetEnumDescriptionString((int)employee.maritalState, typeof(MaritalStateEnum));
                    employee.politicalLandscapeText = employee.politicalLandscape == null ? "" :
                    EnumHelper.GetEnumDescriptionString((int)employee.politicalLandscape, typeof(PoliticalLandscapeEnum));
                    employee.householdRegisterText = employee.householdRegister == null ? "" :
                    EnumHelper.GetEnumDescriptionString((int)employee.householdRegister, typeof(HouseholdRegisterEnum));
                    if (!string.IsNullOrWhiteSpace(employee.curriculumVitae))
                        employee.curriculumVitaeFileName = employee.curriculumVitae.Split("{@yntk@}")[1];
                    if (employee.dateEntry != null)
                    {
                        //计算工龄
                        (int year, int month, int days, string age) = CalculateWorkingAge((DateTime)employee.dateEntry);
                        employee.workingAge = age;
                    }
                    if (employee.dateBirth != null)
                        employee.age = GetAgeByBirthdate((DateTime)employee.dateBirth) + "岁";
                }
                return TkResult<EmployeesInfoDto>.Success(employee);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"获取员工基本信息发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 当前登录用户完善个人信息
        /// </summary>
        /// <param name="input">当前登录用户完善个人信息请求模型</param>
        /// <returns></returns>
        [HttpPut("perfect")]
        public async Task PerfectPersonalInformation([FromBody] EmployeesEditInfoRequestModel input)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                var userId = user.Value;
                if(userId!=input.id) throw YNTKException.Oh(ErrorCode.D1016);
                var entity = await GetEmployeesInfoAsync(r => r.Id == input.id);
                //_ = entity ?? throw YNTKException.Oh(ErrorCode.Employee0001);
                if(input.id== "@yntk@super@admin" && input.account!= "yntk@super@admin")
                    throw YNTKException.Oh(ErrorCode.D5023);

                if (entity != null)
                {
                    #region 唯一信息验证
                    if ((await GetEmployeesInfoAsync(u => u.Account == input.account && u.Id != input.id)) != null)
                        throw YNTKException.Oh(ErrorCode.D5000);
                    if (!string.IsNullOrWhiteSpace(input.mobilePhone) &&
                        (await GetEmployeesInfoAsync(u => u.MobilePhone == input.mobilePhone && u.Id != input.id)) != null)
                        throw YNTKException.Oh(ErrorCode.D5017);
                    if (!string.IsNullOrWhiteSpace(input.certificatesNumber) &&
                      (await GetEmployeesInfoAsync(u => u.CertificatesNumber == input.certificatesNumber && u.Id != input.id)) != null)
                        throw YNTKException.Oh(ErrorCode.D5018);
                    if (!string.IsNullOrWhiteSpace(input.email) &&
                      (await GetEmployeesInfoAsync(u => u.Email == input.email && u.Id != input.id)) != null)
                        throw YNTKException.Oh(ErrorCode.D5019);
                    #endregion

                    string oldHeadIcon = entity.HeadIcon;
                    string oldFrontIdentityCard = entity.FrontIdentityCard;
                    string oldReverseSideIdentityCard = entity.ReverseSideIdentityCard;
                    string oldCurriculumVitae = entity.CurriculumVitae;
                    string oldSignature = entity.Signature;

                    entity = input.Mapper(entity);
                    entity.Sex = input.sex.GetHashCode();//性别(0.男 1.女)
                    entity.Education = input.education.GetHashCode();//最高学历(0.学前教育 1.小学 2.初中 3.中专 4.高中 5.专科 6.本科 7.硕士研究生 8.博士研究生)
                    entity.MaritalState = input.maritalState.GetHashCode();//婚姻状态(0.未婚 1.已婚 2.丧偶 3.离异 4.其它)
                    entity.PoliticalLandscape = input.politicalLandscape.GetHashCode();//政治面貌(0.中共党员 1.中共预备党员 2.共青团员 3.无党派人士 4.群众)
                    entity.HouseholdRegister = input.householdRegister.GetHashCode();//户口性质(0.农业户口 1.居民户口 2.农村户口 3.集体户口)
                    entity.LastModifyTime = DateTime.Now;
                    entity.DutyState = input.dutyState.GetHashCode();//在岗情况(0.正常 1.请假 2.出差)

                    //sqlserver保存员工信息
                    var isOK = await _employeesRepository.Context.Updateable(entity)
                        .WhereColumns(it => new { it.Id }).ExecuteCommandAsync();
                    if (!(isOK > 0)) throw YNTKException.Oh(ErrorCode.Employee0002);

                    //mongodb保存员工信息
                    var update = await _employeesMongoDbRepository.UpdateAsync(entity, _employees, m => m.Id == entity.Id);
                    if (!(update.ModifiedCount > 0)) throw YNTKException.Oh(ErrorCode.Employee0003);

                    #region 同步用户信息
                    await Event.EmitAsync("Employee:UpadteUserInfo", Tuple.Create(entity, userId));
                    #endregion

                    if (!string.IsNullOrWhiteSpace(oldHeadIcon) && entity.HeadIcon != oldHeadIcon)
                        _fileService.DeleteSingleFile(oldHeadIcon);
                    if (!string.IsNullOrWhiteSpace(oldFrontIdentityCard) && entity.FrontIdentityCard != oldFrontIdentityCard)
                        _fileService.DeleteSingleFile(oldFrontIdentityCard);
                    if (!string.IsNullOrWhiteSpace(oldReverseSideIdentityCard) && entity.ReverseSideIdentityCard != oldReverseSideIdentityCard)
                        _fileService.DeleteSingleFile(oldReverseSideIdentityCard);
                    if (!string.IsNullOrWhiteSpace(oldCurriculumVitae) && entity.CurriculumVitae != oldCurriculumVitae)
                        _fileService.DeleteSingleFile(oldCurriculumVitae);
                    if (!string.IsNullOrWhiteSpace(oldSignature) && entity.Signature != oldSignature)
                        _fileService.DeleteSingleFile(oldSignature);
                }
                else
                    await Add(input,userId);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"当前登录用户完善个人信息发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 添加员工信息
        /// </summary>
        /// <param name="input"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        private async Task Add(EmployeesEditInfoRequestModel input, string userId)
        {
            var userInfo = await _tkUsersService.GetUserInfoByUserId(input.id);
            _ = userInfo ?? throw YNTKException.Oh(ErrorCode.Employee0001);

            #region 唯一信息验证
            if ((await _tkUsersService.GetUserInfoAsync(u => u.Account == input.account && u.Id != input.id)) != null)
                throw YNTKException.Oh(ErrorCode.D5000);
            if (!string.IsNullOrWhiteSpace(input.mobilePhone) &&
                (await _tkUsersService.GetUserInfoAsync(u => u.MobilePhone == input.mobilePhone && u.Id != input.id)) != null)
                throw YNTKException.Oh(ErrorCode.D5017);
            if (!string.IsNullOrWhiteSpace(input.certificatesNumber) &&
              (await _tkUsersService.GetUserInfoAsync(u => u.CertificatesNumber == input.certificatesNumber && u.Id != input.id)) != null)
                throw YNTKException.Oh(ErrorCode.D5018);
            if (!string.IsNullOrWhiteSpace(input.email) &&
              (await _tkUsersService.GetUserInfoAsync(u => u.Email == input.email && u.Id != input.id)) != null)
                throw YNTKException.Oh(ErrorCode.D5019);
            #endregion

            var entity = input.Adapt<EmployeesEntity>();
            //entity.Id = YitIdHelper.NextId().ToString();//员工id
            entity.OrganizeId = userInfo.OrganizeId;
            entity.MechanismId = userInfo.ManagerId;
            entity.RoleId = userInfo.RoleId;
            entity.Sex = input.sex.GetHashCode();//性别(0.男 1.女)
            entity.Education = input.education.GetHashCode();//最高学历(0.学前教育 1.小学 2.初中 3.中专 4.高中 5.专科 6.本科 7.硕士研究生 8.博士研究生)
            entity.MaritalState = input.maritalState.GetHashCode();//婚姻状态(0.未婚 1.已婚 2.丧偶 3.离异 4.其它)
            entity.PoliticalLandscape = input.politicalLandscape.GetHashCode();//政治面貌(0.中共党员 1.中共预备党员 2.共青团员 3.无党派人士 4.群众)
            entity.HouseholdRegister = input.householdRegister.GetHashCode();//户口性质(0.农业户口 1.居民户口 2.农村户口 3.集体户口)
            entity.CreatorTime = DateTime.Now;
            entity.DutyState = input.dutyState.GetHashCode();//在岗情况(0.正常 1.请假 2.出差)

            //sqlserver保存员工信息
            var isOK = await _employeesRepository.Context.Insertable(entity).ExecuteCommandAsync();
            if (!(isOK > 0)) throw YNTKException.Oh(ErrorCode.Employee0002);

            //mongodb保存员工信息
            var add = await _employeesMongoDbRepository.AddAsync(entity, _employees);
            if (!add) throw YNTKException.Oh(ErrorCode.Employee0003);

            #region 同步用户信息
            await Event.EmitAsync("Employee:UpadteUserInfo", Tuple.Create(entity, userId));
            #endregion
        }

        /// <summary>
        /// 添加员工(花名册人力资源员工入职录入员工时用)
        /// </summary>
        /// <param name="input">添加员工请求模型</param>
        /// <returns></returns>
        [HttpPost("add")]
        public async Task AddEmployee([FromBody] AddEmployeeRequestModel input)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                var userId = user.Value;
                string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;
                //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
                var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
                if (authenticationType != "2" && authenticationType != "3")
                    throw YNTKException.Oh(ErrorCode.D1016);

                #region 唯一信息验证
                if (!string.IsNullOrWhiteSpace(input.mobilePhone) &&
                    (await _tkUsersService.GetUserInfoAsync(u => u.MobilePhone == input.mobilePhone)) != null)
                    throw YNTKException.Oh(ErrorCode.D5017);
                if (!string.IsNullOrWhiteSpace(input.certificatesNumber) &&
                  (await _tkUsersService.GetUserInfoAsync(u => u.CertificatesNumber == input.certificatesNumber)) != null)
                    throw YNTKException.Oh(ErrorCode.D5018);
                if (!string.IsNullOrWhiteSpace(input.email) &&
                  (await _tkUsersService.GetUserInfoAsync(u => u.Email == input.email)) != null)
                    throw YNTKException.Oh(ErrorCode.D5019);
                #endregion

                var entity = input.Adapt<EmployeesEntity>();
                entity.OrganizeId = organizeId;
                entity.Id = YitIdHelper.NextId().ToString();//员工id
                entity.Account = entity.MobilePhone;//使用手机号作为登录账号
                entity.LaborRelations = input.laborRelations.GetHashCode();//劳动关系(0.抽调 1.合同工 2.派遣)
                entity.Sex = input.sex.GetHashCode();//性别(0.男 1.女)
                entity.PayWay = input.payWay.GetHashCode();//薪酬方式(0.年薪制 1.月薪制)
                entity.State = input.state.GetHashCode();//员工状态(0.实习生 1.试用 2.兼职 3.在职 4.离职 5.停职留薪 6.退休 7.返聘)
                entity.CreatorTime = DateTime.Now;
                entity.DutyState = input.dutyState.GetHashCode();//在岗情况(0.正常 1.请假 2.出差)

                //sqlserver保存员工信息
                var isOK = await _employeesRepository.Context.Insertable(entity).ExecuteCommandAsync();
                if (!(isOK > 0)) throw YNTKException.Oh(ErrorCode.Employee0002);

                //mongodb保存员工信息
                var add = await _employeesMongoDbRepository.AddAsync(entity, _employees);
                if (!add) throw YNTKException.Oh(ErrorCode.Employee0003);

                #region 同步用户信息
                await Event.EmitAsync("Employee:AddUserInfo", Tuple.Create(entity, userId));
                #endregion
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"添加员工发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 修改员工信息(花名册人力资源管理员工信息时用)
        /// </summary>
        /// <param name="input">修改员工信息请求模型</param>
        /// <returns></returns>
        [HttpPut("update")]
        public async Task Update([FromBody] UpdateEmployeeRequestModel input)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                var userId = user.Value;
                string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;
                //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
                var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
                if (authenticationType != "2" && authenticationType != "3")
                    throw YNTKException.Oh(ErrorCode.D1016);

                var entity = await GetEmployeesInfoAsync(r => r.Id == input.id);
                _ = entity ?? throw YNTKException.Oh(ErrorCode.Employee0001);
                if(entity.OrganizeId!= organizeId) throw YNTKException.Oh(ErrorCode.D1016);
                var userInfo = await _tkUsersService.GetUserInfoByUserId(entity.Id);
                if(userInfo!=null && userInfo.AccountType!=2 && userInfo.AccountType!=3)
                    throw YNTKException.Oh(ErrorCode.D1016);

                #region 唯一信息验证
                if (!string.IsNullOrWhiteSpace(input.mobilePhone) &&
                    (await GetEmployeesInfoAsync(u => u.MobilePhone == input.mobilePhone && u.Id != input.id)) != null)
                    throw YNTKException.Oh(ErrorCode.D5017);
                if (!string.IsNullOrWhiteSpace(input.certificatesNumber) &&
                  (await GetEmployeesInfoAsync(u => u.CertificatesNumber == input.certificatesNumber && u.Id != input.id)) != null)
                    throw YNTKException.Oh(ErrorCode.D5018);
                if (!string.IsNullOrWhiteSpace(input.email) &&
                  (await GetEmployeesInfoAsync(u => u.Email == input.email && u.Id != input.id)) != null)
                    throw YNTKException.Oh(ErrorCode.D5019);
                #endregion

                entity = input.Mapper(entity);
                entity.Account = entity.MobilePhone;//使用手机号作为登录账号
                entity.LaborRelations = input.laborRelations.GetHashCode();//劳动关系(0.抽调 1.合同工 2.派遣)
                entity.Sex = input.sex.GetHashCode();//性别(0.男 1.女)
                entity.PayWay = input.payWay.GetHashCode();//薪酬方式(0.年薪制 1.月薪制)
                entity.State = input.state.GetHashCode();//员工状态(0.实习生 1.试用 2.兼职 3.在职 4.离职 5.停职留薪 6.退休 7.返聘)
                entity.LastModifyTime = DateTime.Now;
                entity.DutyState = input.dutyState.GetHashCode();//在岗情况(0.正常 1.请假 2.出差)

                //sqlserver保存员工信息
                var isOK = await _employeesRepository.Context.Updateable(entity)
                    .WhereColumns(it => new { it.Id }).ExecuteCommandAsync();
                if (!(isOK > 0)) throw YNTKException.Oh(ErrorCode.Employee0002);

                //mongodb保存员工信息
                var update = await _employeesMongoDbRepository.UpdateAsync(entity, _employees, m => m.Id == entity.Id);
                if (!(update.ModifiedCount > 0)) throw YNTKException.Oh(ErrorCode.Employee0003);

                #region 同步用户信息
                await Event.EmitAsync("Employee:UpadteUserInfo", Tuple.Create(entity, userId));
                #endregion
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"修改员工信息发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 删除员工
        /// </summary>
        /// <param name="id">员工id</param>
        /// <returns></returns>
        [HttpDelete("delete/{id}")]
        public async Task Delete([Required] string id)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                var userId = user.Value;
                string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;
                //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
                var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
                if (authenticationType != "2" && authenticationType != "3")
                    throw YNTKException.Oh(ErrorCode.D1016);

                var entity = await GetEmployeesInfoAsync(r => r.Id == id);
                _ = entity ?? throw YNTKException.Oh(ErrorCode.Employee0001);
                if (entity.OrganizeId != organizeId) throw YNTKException.Oh(ErrorCode.D1016);
                var userInfo = await _tkUsersService.GetUserInfoByUserId(entity.Id);
                if (userInfo!=null && userInfo.AccountType != 2 && userInfo.AccountType != 3)
                    throw YNTKException.Oh(ErrorCode.D1016);
                if(userInfo!=null && userInfo.AccountType==2) throw YNTKException.Oh(ErrorCode.D5024);

                //sqlserver删除员工信息
                var isOK = await _employeesRepository.DeleteAsync(r=>r.Id==id);
                if (!(isOK > 0)) throw YNTKException.Oh(ErrorCode.Employee0004);

                //mongodb删除员工信息
                var delete = await _employeesMongoDbRepository.DeleteAsync(_employees, m => m.Id == entity.Id);
                if (!(delete > 0)) throw YNTKException.Oh(ErrorCode.Employee0005);

                #region 同步用户信息
                await Event.EmitAsync("Employee:DeleteUserInfo", id);
                #endregion

                if (!string.IsNullOrWhiteSpace(entity.HeadIcon))
                    _fileService.DeleteSingleFile(entity.HeadIcon);
                if (!string.IsNullOrWhiteSpace(entity.FrontIdentityCard))
                    _fileService.DeleteSingleFile(entity.FrontIdentityCard);
                if (!string.IsNullOrWhiteSpace(entity.ReverseSideIdentityCard))
                    _fileService.DeleteSingleFile(entity.ReverseSideIdentityCard);
                if (!string.IsNullOrWhiteSpace(entity.CurriculumVitae))
                    _fileService.DeleteSingleFile(entity.CurriculumVitae);

                //根据条件获取员工教育经历信息
                await DeleteEducationsAsync(id);
                //删除员工家庭成员数据
                await DeleteFamilyMembersAsync(id);
                //删除员工工作经历数据
                await DeleteWorksAsync(id);
                //删除员工技术职称证书数据
                await DeleteCertificatesAsync(id);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"删除员工发生异常：{ex.Message}");
            }
        }
        #endregion

        #region 教育经历
        /// <summary>
        /// 获取员工教育经历数据
        /// </summary>
        /// <param name="employeeId">员工id</param>
        /// <returns></returns>
        [HttpGet("education/gets")]
        public async Task<TkResult<List<EducationListDto>>> GetEducationList([Required] string employeeId)
        {
            try
            {
                //先从mongodb中获取
                var result = await _educationMongoDbRepository.GetListAsync(_educations,m=>m.EmployeeId== employeeId);
                if (!result.Any())
                {
                    //再从sqlserver中获取
                    result = await _educationRepository.Entities.Where(r => r.EmployeeId == employeeId).ToListAsync();
                }
                var dtos = result.Adapt<List<EducationListDto>>();
                if (dtos.Any())
                {
                    dtos = dtos.OrderByDescending(r=>r.education).ToList();
                    dtos.ForEach(item =>
                    {
                        item.educationText = item.education == null ? "" :
                         EnumHelper.GetEnumDescriptionString((int)item.education, typeof(EducationEnum));
                        item.degreeText = item.degree == null ? "" :
                        EnumHelper.GetEnumDescriptionString((int)item.degree, typeof(DegreeEnum));
                    });
                }
                return TkResult<List<EducationListDto>>.Success(dtos);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"获取员工教育经历数据发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 添加教育经历
        /// </summary>
        /// <param name="input">添加教育经历请求模型</param>
        /// <returns></returns>
        [HttpPost("education/add")]
        public async Task AddEducation([FromBody] AddEducationRequestModel input)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                var userId = user.Value;
                var entity = input.Adapt<EducationExperiencesEntity>();
                entity.Id = YitIdHelper.NextId().ToString();
                entity.EmployeeId = userId;//员工id
                entity.Education = input.education.GetHashCode();//学历(0.学前教育 1.小学 2.初中 3.中专 4.高中 5.专科 6.本科 7.硕士研究生 8.博士研究生)
                entity.Degree = input.degree.GetHashCode();//学位(0.无 1.学士 2.硕士 3.博士)

                //sqlserver保存员工教育经历信息
                var isOK = await _educationRepository.Context.Insertable(entity).ExecuteCommandAsync();
                if (!(isOK > 0)) throw YNTKException.Oh(ErrorCode.Employee0006);

                //mongodb保存员工教育经历信息
                var add = await _educationMongoDbRepository.AddAsync(entity, _educations);
                if (!add) throw YNTKException.Oh(ErrorCode.Employee0007);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"添加教育经历发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 修改教育经历
        /// </summary>
        /// <param name="input">修改教育经历请求模型</param>
        /// <returns></returns>
        [HttpPut("education/update")]
        public async Task UpdateEducation([FromBody] UpdateEducationRequestModel input)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                var userId = user.Value;
                var entity = await GetEducationInfoAsync(m=>m.Id==input.id);
                _ = entity ?? throw YNTKException.Oh(ErrorCode.Employee0008);
                if(entity.EmployeeId!=userId) throw YNTKException.Oh(ErrorCode.D1016);

                string oldGraduationCardFilePath = entity.GraduationCardFilePath;
                string oldDegreeFilePath = entity.DegreeFilePath;
                entity = input.Mapper(entity);
                entity.Education = input.education.GetHashCode();//学历(0.学前教育 1.小学 2.初中 3.中专 4.高中 5.专科 6.本科 7.硕士研究生 8.博士研究生)
                entity.Degree = input.degree.GetHashCode();//学位(0.无 1.学士 2.硕士 3.博士)

                //sqlserver保存员工教育经历信息
                var isOK = await _educationRepository.Context.Updateable(entity)
                    .WhereColumns(it => new { it.Id }).ExecuteCommandAsync();
                if (!(isOK > 0)) throw YNTKException.Oh(ErrorCode.Employee0006);

                //mongodb保存员工教育经历信息
                var update = await _educationMongoDbRepository.UpdateAsync(entity, _educations, m => m.Id == entity.Id);
                if (!(update.ModifiedCount > 0)) throw YNTKException.Oh(ErrorCode.Employee0007);

                if (!string.IsNullOrWhiteSpace(oldGraduationCardFilePath) && entity.GraduationCardFilePath != oldGraduationCardFilePath)
                    _fileService.DeleteSingleFile(oldGraduationCardFilePath);
                if (!string.IsNullOrWhiteSpace(oldDegreeFilePath) && entity.DegreeFilePath != oldDegreeFilePath)
                    _fileService.DeleteSingleFile(oldDegreeFilePath);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"修改教育经历发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 删除教育经历
        /// </summary>
        /// <param name="id">教育经历id</param>
        /// <returns></returns>
        [HttpDelete("education/delete/{id}")]
        public async Task DeleteEducation([Required] string id)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                var userId = user.Value;
                var entity = await GetEducationInfoAsync(m => m.Id == id);
                _ = entity ?? throw YNTKException.Oh(ErrorCode.Employee0008);
                if (entity.EmployeeId != userId) throw YNTKException.Oh(ErrorCode.D1016);

                //sqlserver删除员工教育经历信息
                var isOK = await _educationRepository.DeleteAsync(r => r.Id == id);
                if (!(isOK > 0)) throw YNTKException.Oh(ErrorCode.Employee0009);

                //mongodb删除员工教育经历信息
                var delete = await _educationMongoDbRepository.DeleteAsync(_educations, m => m.Id == entity.Id);
                if (!(delete > 0)) throw YNTKException.Oh(ErrorCode.Employee0010);

                if (!string.IsNullOrWhiteSpace(entity.GraduationCardFilePath))
                    _fileService.DeleteSingleFile(entity.GraduationCardFilePath);
                if (!string.IsNullOrWhiteSpace(entity.DegreeFilePath))
                    _fileService.DeleteSingleFile(entity.DegreeFilePath);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"删除教育经历发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 删除员工教育经历数据
        /// </summary>
        /// <param name="employeeId">员工id</param>
        /// <returns></returns>
        private async Task DeleteEducationsAsync(string employeeId)
        {
            //先从mongodb中获取
            var result = await _educationMongoDbRepository.GetListAsync(_educations, m => m.EmployeeId == employeeId);
            if (!result.Any())
            {
                //再从sqlserver中获取
                result = await _educationRepository.Entities.Where(r => r.EmployeeId == employeeId).ToListAsync();
            }
            if (result.Any())
            {
                await _educationMongoDbRepository.DeleteAsync(_educations, r => r.EmployeeId == employeeId);
                await _educationRepository.DeleteAsync(r => r.EmployeeId == employeeId);
                var filePaths= result.Where(r=>!string.IsNullOrWhiteSpace(r.GraduationCardFilePath))
                    ?.ToList()?.Select(r => r.GraduationCardFilePath)?.Distinct()?.ToList()
                    .Union(
                         result.Where(r => !string.IsNullOrWhiteSpace(r.DegreeFilePath))
                         ?.ToList()?.Select(r => r.DegreeFilePath)?.Distinct()?.ToList()
                        ).ToList();
                if (filePaths.Any()) _fileService.DeleteFileByPaths(filePaths);
            }
        }

        /// <summary>
        /// 根据条件获取员工教育经历信息
        /// </summary>
        /// <param name="where">条件</param>
        /// <returns></returns>
        private async Task<EducationExperiencesEntity> GetEducationInfoAsync(Expression<Func<EducationExperiencesEntity, bool>> where)
        {
            //从从mongodb中获取
            var entity = await _educationMongoDbRepository.GetAsync(_educations, where);
            //再从sqlserver中获取
            if (entity == null) entity = await _educationRepository.FirstOrDefaultAsync(where);
            return entity;
        }
        #endregion

        #region 家庭成员
        /// <summary>
        /// 获取员工家庭成员数据
        /// </summary>
        /// <param name="employeeId">员工id</param>
        /// <returns></returns>
        [HttpGet("familymember/gets")]
        public async Task<TkResult<List<FamilyMemberListDto>>> GetFamilyMemberList([Required] string employeeId)
        {
            try
            {
                //先从mongodb中获取
                var result = await _familyMongoDbRepository.GetListAsync(_familymembers, m => m.EmployeeId == employeeId);
                if (!result.Any())
                {
                    //再从sqlserver中获取
                    result = await _familyRepository.Entities.Where(r => r.EmployeeId == employeeId).ToListAsync();
                }
                var dtos = result.Adapt<List<FamilyMemberListDto>>();
                return TkResult<List<FamilyMemberListDto>>.Success(dtos);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"获取员工家庭成员数据发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 添加家庭成员
        /// </summary>
        /// <param name="input">添加家庭成员请求模型</param>
        /// <returns></returns>
        [HttpPost("familymember/add")]
        public async Task AddFamilyMember([FromBody] AddFamilyMemberRequestModel input)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                var userId = user.Value;
                var entity = input.Adapt<FamilyMembersEntity>();
                entity.Id = YitIdHelper.NextId().ToString();
                entity.EmployeeId = userId;//员工id

                //sqlserver保存员工教家庭成员信息
                var isOK = await _familyRepository.Context.Insertable(entity).ExecuteCommandAsync();
                if (!(isOK > 0)) throw YNTKException.Oh(ErrorCode.Employee0011);

                //mongodb保存员工家庭成员信息
                var add = await _familyMongoDbRepository.AddAsync(entity, _familymembers);
                if (!add) throw YNTKException.Oh(ErrorCode.Employee0012);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"添加家庭成员发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 修改家庭成员
        /// </summary>
        /// <param name="input">修改家庭成员请求模型</param>
        /// <returns></returns>
        [HttpPut("familymember/update")]
        public async Task UpdateFamilyMember([FromBody] UpdateFamilyMemberRequestModel input)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                var userId = user.Value;
                var entity = await GetFamilyMemberInfoAsync(m => m.Id == input.id);
                _ = entity ?? throw YNTKException.Oh(ErrorCode.Employee0013);
                if (entity.EmployeeId != userId) throw YNTKException.Oh(ErrorCode.D1016);
                entity = input.Mapper(entity);

                //sqlserver保存员工家庭成员信息
                var isOK = await _familyRepository.Context.Updateable(entity)
                    .WhereColumns(it => new { it.Id }).ExecuteCommandAsync();
                if (!(isOK > 0)) throw YNTKException.Oh(ErrorCode.Employee0011);

                //mongodb保存员工家庭成员信息
                var update = await _familyMongoDbRepository.UpdateAsync(entity, _familymembers, m => m.Id == entity.Id);
                if (!(update.ModifiedCount > 0)) throw YNTKException.Oh(ErrorCode.Employee0012);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"修改家庭成员发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 删除家庭成员
        /// </summary>
        /// <param name="id">家庭成员id</param>
        /// <returns></returns>
        [HttpDelete("familymember/delete/{id}")]
        public async Task DeleteFamilyMember([Required] string id)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                var userId = user.Value;
                var entity = await GetFamilyMemberInfoAsync(m => m.Id == id);
                _ = entity ?? throw YNTKException.Oh(ErrorCode.Employee0013);
                if (entity.EmployeeId != userId) throw YNTKException.Oh(ErrorCode.D1016);

                //sqlserver删除员工家庭成员信息
                var isOK = await _familyRepository.DeleteAsync(r => r.Id == id);
                if (!(isOK > 0)) throw YNTKException.Oh(ErrorCode.Employee0014);

                //mongodb删除员工家庭成员信息
                var delete = await _familyMongoDbRepository.DeleteAsync(_familymembers, m => m.Id == entity.Id);
                if (!(delete > 0)) throw YNTKException.Oh(ErrorCode.Employee0015);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"删除家庭成员发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 删除员工家庭成员数据
        /// </summary>
        /// <param name="employeeId">员工id</param>
        /// <returns></returns>
        private async Task DeleteFamilyMembersAsync(string employeeId)
        {
            //先从mongodb中获取
            var result = await _familyMongoDbRepository.GetListAsync(_familymembers, m => m.EmployeeId == employeeId);
            if (!result.Any())
            {
                //再从sqlserver中获取
                result = await _familyRepository.Entities.Where(r => r.EmployeeId == employeeId).ToListAsync();
            }
            if (result.Any())
            {
                await _familyMongoDbRepository.DeleteAsync(_familymembers, r => r.EmployeeId == employeeId);
                await _familyRepository.DeleteAsync(r => r.EmployeeId == employeeId);
            }
        }

        /// <summary>
        /// 根据条件获取员工家庭成员信息
        /// </summary>
        /// <param name="where">条件</param>
        /// <returns></returns>
        private async Task<FamilyMembersEntity> GetFamilyMemberInfoAsync(Expression<Func<FamilyMembersEntity, bool>> where)
        {
            //从从mongodb中获取
            var entity = await _familyMongoDbRepository.GetAsync(_familymembers, where);
            //再从sqlserver中获取
            if (entity == null) entity = await _familyRepository.FirstOrDefaultAsync(where);
            return entity;
        }
        #endregion

        #region 工作经历
        /// <summary>
        /// 获取员工工作经历数据
        /// </summary>
        /// <param name="employeeId">员工id</param>
        /// <returns></returns>
        [HttpGet("works/gets")]
        public async Task<TkResult<List<WorkExperienceListDto>>> GetWorkExperienceList([Required] string employeeId)
        {
            try
            {
                //先从mongodb中获取
                var result = await _workMongoDbRepository.GetListAsync(_works, m => m.EmployeeId == employeeId);
                if (!result.Any())
                {
                    //再从sqlserver中获取
                    result = await _workRepository.Entities.Where(r => r.EmployeeId == employeeId).ToListAsync();
                }
                var dtos = result.Adapt<List<WorkExperienceListDto>>();
                if (dtos.Any())
                {
                    dtos = dtos.OrderByDescending(r => r.endDate).ToList();
                    dtos.ForEach(work =>
                    {
                        if (!string.IsNullOrWhiteSpace(work.officeFilePath))
                            work.officeFileName = work.officeFilePath.Split("{@yntk@}")[1];
                        if (!string.IsNullOrWhiteSpace(work.dismissalFilePath))
                            work.dismissalFileName = work.dismissalFilePath.Split("{@yntk@}")[1];
                    });
                }
                return TkResult<List<WorkExperienceListDto>>.Success(dtos);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"获取员工工作经历数据发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 添加工作经历
        /// </summary>
        /// <param name="input">添加工作经历请求模型</param>
        /// <returns></returns>
        [HttpPost("works/add")]
        public async Task AddWork([FromBody] AddWorkExperienceRequestModel input)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                var userId = user.Value;
                var entity = input.Adapt<WorkExperiencesEntity>();
                entity.Id = YitIdHelper.NextId().ToString();
                entity.EmployeeId = userId;//员工id

                //sqlserver保存员工工作经历信息
                var isOK = await _workRepository.Context.Insertable(entity).ExecuteCommandAsync();
                if (!(isOK > 0)) throw YNTKException.Oh(ErrorCode.Employee0016);

                //mongodb保存员工工作经历信息
                var add = await _workMongoDbRepository.AddAsync(entity, _works);
                if (!add) throw YNTKException.Oh(ErrorCode.Employee0017);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"添加工作经历发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 修改工作经历
        /// </summary>
        /// <param name="input">修改工作经历请求模型</param>
        /// <returns></returns>
        [HttpPut("works/update")]
        public async Task UpdateWork([FromBody] UpdateWorkExperienceRequestModel input)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                var userId = user.Value;
                var entity = await GetWorkExperienceInfoAsync(m => m.Id == input.id);
                _ = entity ?? throw YNTKException.Oh(ErrorCode.Employee0018);
                if (entity.EmployeeId != userId) throw YNTKException.Oh(ErrorCode.D1016);

                string oldOfficeFilePath = entity.OfficeFilePath;
                string oldDismissalFilePath = entity.DismissalFilePath;
                entity = input.Mapper(entity);

                //sqlserver保存员工工作经历信息
                var isOK = await _workRepository.Context.Updateable(entity)
                    .WhereColumns(it => new { it.Id }).ExecuteCommandAsync();
                if (!(isOK > 0)) throw YNTKException.Oh(ErrorCode.Employee0016);

                //mongodb保存员工工作经历信息
                var update = await _workMongoDbRepository.UpdateAsync(entity, _works, m => m.Id == entity.Id);
                if (!(update.ModifiedCount > 0)) throw YNTKException.Oh(ErrorCode.Employee0017);

                if (!string.IsNullOrWhiteSpace(oldOfficeFilePath) && entity.OfficeFilePath != oldOfficeFilePath)
                    _fileService.DeleteSingleFile(oldOfficeFilePath);
                if (!string.IsNullOrWhiteSpace(oldDismissalFilePath) && entity.DismissalFilePath != oldDismissalFilePath)
                    _fileService.DeleteSingleFile(oldDismissalFilePath);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"修改工作经历发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 删除工作记录
        /// </summary>
        /// <param name="id">工作经历id</param>
        /// <returns></returns>
        [HttpDelete("works/delete/{id}")]
        public async Task DeleteWork([Required] string id)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                var userId = user.Value;
                var entity = await GetWorkExperienceInfoAsync(m => m.Id == id);
                _ = entity ?? throw YNTKException.Oh(ErrorCode.Employee0018);
                if (entity.EmployeeId != userId) throw YNTKException.Oh(ErrorCode.D1016);

                //sqlserver删除员工工作经历信息
                var isOK = await _workRepository.DeleteAsync(r => r.Id == id);
                if (!(isOK > 0)) throw YNTKException.Oh(ErrorCode.Employee0019);

                //mongodb删除员工工作经历信息
                var delete = await _workMongoDbRepository.DeleteAsync(_works, m => m.Id == entity.Id);
                if (!(delete > 0)) throw YNTKException.Oh(ErrorCode.Employee0020);

                if (!string.IsNullOrWhiteSpace(entity.OfficeFilePath))
                    _fileService.DeleteSingleFile(entity.OfficeFilePath);
                if (!string.IsNullOrWhiteSpace(entity.DismissalFilePath))
                    _fileService.DeleteSingleFile(entity.DismissalFilePath);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"删除工作经历发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 删除员工工作经历数据
        /// </summary>
        /// <param name="employeeId">员工id</param>
        /// <returns></returns>
        private async Task DeleteWorksAsync(string employeeId)
        {
            //先从mongodb中获取
            var result = await _workMongoDbRepository.GetListAsync(_works, m => m.EmployeeId == employeeId);
            if (!result.Any())
            {
                //再从sqlserver中获取
                result = await _workRepository.Entities.Where(r => r.EmployeeId == employeeId).ToListAsync();
            }
            if (result.Any())
            {
                await _workMongoDbRepository.DeleteAsync(_works, r => r.EmployeeId == employeeId);
                await _workRepository.DeleteAsync(r => r.EmployeeId == employeeId);
                var filePaths = result.Where(r => !string.IsNullOrWhiteSpace(r.OfficeFilePath))
                    ?.ToList()?.Select(r => r.OfficeFilePath)?.Distinct()?.ToList()
                    .Union(
                         result.Where(r => !string.IsNullOrWhiteSpace(r.DismissalFilePath))
                         ?.ToList()?.Select(r => r.DismissalFilePath)?.Distinct()?.ToList()
                        ).ToList();
                if (filePaths.Any()) _fileService.DeleteFileByPaths(filePaths);
            }
        }

        /// <summary>
        /// 根据条件获取员工工作经历信息
        /// </summary>
        /// <param name="where">条件</param>
        /// <returns></returns>
        private async Task<WorkExperiencesEntity> GetWorkExperienceInfoAsync(Expression<Func<WorkExperiencesEntity, bool>> where)
        {
            //从从mongodb中获取
            var entity = await _workMongoDbRepository.GetAsync(_works, where);
            //再从sqlserver中获取
            if (entity == null) entity = await _workRepository.FirstOrDefaultAsync(where);
            return entity;
        }
        #endregion

        #region 技术职称证书
        /// <summary>
        /// 获取员工技术职称证书数据
        /// </summary>
        /// <param name="employeeId">员工id</param>
        /// <returns></returns>
        [HttpGet("crtificates/gets")]
        public async Task<TkResult<List<TechnicalCertificateListDto>>> GetTechnicalCertificateList([Required] string employeeId)
        {
            try
            {
                //先从mongodb中获取
                var result = await _certificateMongoDbRepository.GetListAsync(_technicalcertificates, m => m.EmployeeId == employeeId);
                if (!result.Any())
                {
                    //再从sqlserver中获取
                    result = await _certificateRepository.Entities.Where(r => r.EmployeeId == employeeId).ToListAsync();
                }
                var dtos = result.Adapt<List<TechnicalCertificateListDto>>();
                dtos = dtos?.OrderByDescending(r => r.releaseDate)?.ToList();
                return TkResult<List<TechnicalCertificateListDto>>.Success(dtos);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"获取员工技术职称证书数据发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 添加技术职称证书
        /// </summary>
        /// <param name="input">添加技术职称证书请求模型</param>
        /// <returns></returns>
        [HttpPost("crtificates/add")]
        public async Task AddCertificate([FromBody] AddTechnicalCertificateRequestModel input)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                var userId = user.Value;
                var entity = input.Adapt<TechnicalCertificateEntity>();
                entity.Id = YitIdHelper.NextId().ToString();
                entity.EmployeeId = userId;//员工id

                //sqlserver保存员工技术职称证书信息
                var isOK = await _workRepository.Context.Insertable(entity).ExecuteCommandAsync();
                if (!(isOK > 0)) throw YNTKException.Oh(ErrorCode.Employee0021);

                //mongodb保存员工技术职称证书信息
                var add = await _certificateMongoDbRepository.AddAsync(entity, _technicalcertificates);
                if (!add) throw YNTKException.Oh(ErrorCode.Employee0022);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"添加技术职称证书发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 修改技术职称证书
        /// </summary>
        /// <param name="input">修改技术职称证书请求模型</param>
        /// <returns></returns>
        [HttpPut("crtificates/update")]
        public async Task UpdateCertificate([FromBody] UpdateTechnicalCertificateRequestModel input)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                var userId = user.Value;
                var entity = await GetTechnicalCertificateInfoAsync(m => m.Id == input.id);
                _ = entity ?? throw YNTKException.Oh(ErrorCode.Employee0023);
                if (entity.EmployeeId != userId) throw YNTKException.Oh(ErrorCode.D1016);

                string oldCertificateFilePath = entity.CertificateFilePath;
                entity = input.Mapper(entity);

                //sqlserver保存员工技术职称证书信息
                var isOK = await _certificateRepository.Context.Updateable(entity)
                    .WhereColumns(it => new { it.Id }).ExecuteCommandAsync();
                if (!(isOK > 0)) throw YNTKException.Oh(ErrorCode.Employee0021);

                //mongodb保存员工技术职称证书信息
                var update = await _certificateMongoDbRepository.UpdateAsync(entity, _technicalcertificates, m => m.Id == entity.Id);
                if (!(update.ModifiedCount > 0)) throw YNTKException.Oh(ErrorCode.Employee0022);

                if (!string.IsNullOrWhiteSpace(oldCertificateFilePath) && entity.CertificateFilePath != oldCertificateFilePath)
                    _fileService.DeleteSingleFile(oldCertificateFilePath);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"修改技术职称证书发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 删除技术职称证书
        /// </summary>
        /// <param name="id">技术职称证书id</param>
        /// <returns></returns>
        [HttpDelete("crtificates/delete/{id}")]
        public async Task DeleteCertificate([Required] string id)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                var userId = user.Value;
                var entity = await GetTechnicalCertificateInfoAsync(m => m.Id == id);
                _ = entity ?? throw YNTKException.Oh(ErrorCode.Employee0023);
                if (entity.EmployeeId != userId) throw YNTKException.Oh(ErrorCode.D1016);

                //sqlserver删除员工技术职称证书信息
                var isOK = await _certificateRepository.DeleteAsync(r => r.Id == id);
                if (!(isOK > 0)) throw YNTKException.Oh(ErrorCode.Employee0024);

                //mongodb删除员工技术职称证书信息
                var delete = await _certificateMongoDbRepository.DeleteAsync(_technicalcertificates, m => m.Id == entity.Id);
                if (!(delete > 0)) throw YNTKException.Oh(ErrorCode.Employee0025);

                if (!string.IsNullOrWhiteSpace(entity.CertificateFilePath))
                    _fileService.DeleteSingleFile(entity.CertificateFilePath);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"删除技术职称证书发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 删除员工技术职称证书数据
        /// </summary>
        /// <param name="employeeId">员工id</param>
        /// <returns></returns>
        private async Task DeleteCertificatesAsync(string employeeId)
        {
            //先从mongodb中获取
            var result = await _certificateMongoDbRepository.GetListAsync(_technicalcertificates, m => m.EmployeeId == employeeId);
            if (!result.Any())
            {
                //再从sqlserver中获取
                result = await _certificateRepository.Entities.Where(r => r.EmployeeId == employeeId).ToListAsync();
            }
            if (result.Any())
            {
                await _certificateMongoDbRepository.DeleteAsync(_technicalcertificates, r => r.EmployeeId == employeeId);
                await _certificateRepository.DeleteAsync(r => r.EmployeeId == employeeId);
                var filePaths = result.Where(r => !string.IsNullOrWhiteSpace(r.CertificateFilePath))
                    ?.ToList()?.Select(r => r.CertificateFilePath)?.Distinct()?.ToList();
                if (filePaths.Any()) _fileService.DeleteFileByPaths(filePaths);
            }
        }

        /// <summary>
        /// 根据条件获取员工技术职称证书信息
        /// </summary>
        /// <param name="where">条件</param>
        /// <returns></returns>
        private async Task<TechnicalCertificateEntity> GetTechnicalCertificateInfoAsync(Expression<Func<TechnicalCertificateEntity, bool>> where)
        {
            //从从mongodb中获取
            var entity = await _certificateMongoDbRepository.GetAsync(_technicalcertificates, where);
            //再从sqlserver中获取
            if (entity == null) entity = await _certificateRepository.FirstOrDefaultAsync(where);
            return entity;
        }
        #endregion



        /// <summary>
        /// 同步员工数据(开发人员同步专用)
        /// </summary>
        /// <param name="type">0.员工同步用户 1.用户同步员工</param>
        /// <param name="organizeId">要同步的组织id</param>
        /// <param name="mechanismId">要同步的机构id</param>
        /// <param name="roleId">要同步的角色id</param>
        /// <returns></returns>
        [HttpPut("synchronous/{type}")]
        public async Task Synchronous([Required] int type, string organizeId,string mechanismId,string roleId)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string userId = user.Value;
                //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
                var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
                if (authenticationType != "1" || (type != 0 && type != 1)) throw YNTKException.Oh(ErrorCode.D1016);

                _employeesRepository.Ado.BeginTran();
                Expression<Func<UserEntity, bool>> where = r => r.AccountType != 4 && r.AccountType != 5 && r.DeleteMark == null;
                if (!string.IsNullOrWhiteSpace(organizeId)) where = where.And(r => r.OrganizeId == organizeId);
                string queryMechanismId = "";
                if (!string.IsNullOrWhiteSpace(mechanismId))
                {
                    queryMechanismId = await _mechanismService.GetIdAsync(mechanismId, organizeId);
                    where = where.And(r => r.MechanismId == queryMechanismId);
                }
                if (!string.IsNullOrWhiteSpace(roleId)) where = where.And(r => r.RoleId == roleId);
                var users = await _tkUsersService.GetUserListAsync(where);

                Expression<Func<EmployeesEntity, bool>> employeeWhere = r => 1 == 1;
                if (!string.IsNullOrWhiteSpace(organizeId))
                    employeeWhere = employeeWhere.And(r => r.OrganizeId == organizeId);
                if (!string.IsNullOrWhiteSpace(queryMechanismId))
                    employeeWhere = employeeWhere.And(r => r.MechanismId == queryMechanismId);
                if (!string.IsNullOrWhiteSpace(roleId))
                    employeeWhere = employeeWhere.And(r => r.RoleId == roleId);
                var employees = await _employeesMongoDbRepository.GetListAsync(_employees, employeeWhere);
                if (!employees.Any()) employees = await _employeesRepository.Entities.Where(employeeWhere).ToListAsync();

                if (type == 0)
                {
                    if (!employees.Any()) return;
                    employees = !users.Any() ? employees :
                        employees.Where(e => !users.Select(u => u.Id).ToList().Contains(e.Id))?.ToList();
                    if (!employees.Any()) return;
                    var entitys = new List<UserEntity>();
                    string secretkey = Guid.NewGuid().ToString();
                    string password = MD5Encryption.Encrypt(CommonConst.DEFAULT_PASSWORD + secretkey);
                    employees.ForEach(employee =>
                    {
                        entitys.Add(new UserEntity()
                        {
                            Id = employee.Id,
                            OrganizeId = employee.OrganizeId,
                            MechanismId = employee.MechanismId,
                            RoleId = employee.RoleId,
                            Account = employee.Account,
                            RealName = employee.RealName,
                            CertificatesNumber = employee.CertificatesNumber,
                            MobilePhone = employee.MobilePhone,
                            Email = employee.Email,
                            CreatorTime = employee.CreatorTime,
                            LastModifyTime = employee.LastModifyTime,
                            Secretkey = secretkey,
                            Password = password,
                            EnabledMark = 1,
                            CreatorUserId = userId,
                            LastModifyUserId = userId
                        });
                    });
                    await _tkUsersService.BatchAddUsersAsync(entitys);
                }
                else
                {
                    if (!users.Any()) return;
                    users = !employees.Any() ? users :
                        users.Where(u => !employees.Select(e => e.Id).ToList().Contains(u.Id))?.ToList();
                    if (!users.Any()) return;
                    var entitys = new List<EmployeesEntity>();
                    users.ForEach(user =>
                    {
                        entitys.Add(new EmployeesEntity()
                        {
                            Id = user.Id,
                            OrganizeId = user.OrganizeId,
                            MechanismId = user.MechanismId,
                            RoleId = user.RoleId,
                            Account = user.Account,
                            RealName = user.RealName,
                            CertificatesNumber = user.CertificatesNumber,
                            MobilePhone = user.MobilePhone,
                            Email = user.Email,
                            CreatorTime = user.CreatorTime,
                            LastModifyTime = user.LastModifyTime
                        });
                    });
                    await _employeesRepository.Context.Insertable(entitys).ExecuteCommandAsync();
                    await _employeesMongoDbRepository.AddListAsync(entitys, _employees);
                }

                _employeesRepository.Ado.CommitTran();
            }
            catch (Exception ex)
            {
                _employeesRepository.Ado.RollbackTran();
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"{(type==0 ? "员工同步用户" : "用户同步员工")}数据发生异常：{ex.Message}");
            }
        }      

        /// <summary>
        /// 根据出生日期（年月日）计算年龄
        /// </summary>
        /// <param name="birthdate">出生日期</param>
        /// <returns></returns>
        private static int GetAgeByBirthdate(DateTime birthdate)
        {
            DateTime now = DateTime.Now;
            int age = now.Year - birthdate.Year;
            if (now.Month < birthdate.Month || (now.Month == birthdate.Month && now.Day < birthdate.Day))
            {
                age--;
            }
            return age < 0 ? 0 : age;
        }

        /// <summary>
        /// 计算工龄
        /// </summary>
        /// <param name="dateEntry">入职日期</param>
        /// <returns></returns>
        private static (int year, int month, int days, string age) CalculateWorkingAge(DateTime dateEntry)
        {
            try
            {
                var endDate = DateTime.Now;
                if (endDate < dateEntry) return (0, 0, 0, "");
                Calendar startCalendar = new GregorianCalendar(dateEntry.Year, dateEntry.Month - 1, dateEntry.Day);
                Calendar now = Calendar.GetInstance(Globalization.CultureInfo.CurrentCulture);
                now.SetTime(endDate);
                int day = now.Get(CalendarEnum.DayOfMonth) - startCalendar.Get(CalendarEnum.DayOfMonth);
                //月份从0开始计算，所以需要+1
                int month = (now.Get(CalendarEnum.Month) + 1) - (startCalendar.Get(CalendarEnum.Month) + 1);
                int year = now.Get(CalendarEnum.Year) - startCalendar.Get(CalendarEnum.Year);
                //按照减法原理，先day相减，不够向month借；然后month相减，不够向year借；最后year相减。
                if (day < 0)
                {
                    month -= 1;
                    now.Set(CalendarEnum.Month, -1);//得到上一个月，用来得到上个月的天数。
                    day += now.GetMaximum(CalendarEnum.DayOfMonth);
                }
                if (month < 0)
                {
                    month = (month + 12) % 12;
                    year--;
                }
                StringBuilder tag = new StringBuilder();
                if (year > 0) tag.Append(year + "年");
                if (month > 0) tag.Append(month + "个月");
                if (day > 0) tag.Append(day + "天"); tag.Append(day + "天");
                if (year == 0 && month == 0 && day == 0) tag.Append("今日入职");
                if (year < 0) year = 0;
                return (year, month, day, tag.ToString());
            }
            catch
            {
                return (0, 0, 0, "");
            }
        }

        #region PublicMethod
        /// <summary>
        /// 根据员工id获取员工信息
        /// </summary>
        /// <param name="employeeId">员工id</param>
        /// <returns></returns>
        [NonAction]
        public async Task<EmployeesEntity> GetEmployeeInfoAsync(string employeeId)
        {
            //先从mongodb数据库中获取
            var entity = await _employeesMongoDbRepository.GetAsync(_employees,m=>m.Id== employeeId);
            //再从sqlserver数据库中获取
            if (entity == null) entity = await _employeesRepository.FirstOrDefaultAsync(r=>r.Id== employeeId);
            return entity;
        }

        /// <summary>
        /// 根据条件获取员工信息
        /// </summary>
        /// <param name="where">条件</param>
        /// <returns></returns>
        [NonAction]
        public async Task<EmployeesEntity> GetEmployeesInfoAsync(Expression<Func<EmployeesEntity, bool>> where)
        {
            //先从mongodb数据库中获取
            var entity = await _employeesMongoDbRepository.GetAsync(_employees, where);
            //再从sqlserver数据库中获取
            if (entity == null) entity = await _employeesRepository.FirstOrDefaultAsync(where);
            return entity;
        }

        /// <summary>
        /// 根据条件获取员工数据
        /// </summary>
        /// <param name="where">条件</param>
        /// <returns></returns>
        [NonAction]
        public async Task<List<EmployeesEntity>> GetEmployeesListAsync(Expression<Func<EmployeesEntity, bool>> where)
        {
            //先从mongodb数据库中获取
            var result = await _employeesMongoDbRepository.GetListAsync(_employees,where);
            //再从sqlserver数据库中获取
            if (!result.Any()) result = await _employeesRepository.Entities.Where(where).ToListAsync();
            return result;
        }

        /// <summary>
        /// 添加员工信息
        /// </summary>
        /// <param name="model">员工信息</param>
        /// <returns></returns>
        [NonAction]
        public async Task AddEmployeesAsync(EmployeesEntity model)
        {
            if ((await GetEmployeesInfoAsync(e => e.Id == model.Id)) != null) return;
            //添加员工信息到sqlserver
            await _employeesRepository.Context.Insertable(model).ExecuteReturnEntityAsync();
            //添加员工信息到mongodb
            await _employeesMongoDbRepository.AddAsync(model, _employees);
        }

        /// <summary>
        /// 修改员工信息
        /// </summary>
        /// <param name="model">员工信息</param>
        /// <returns></returns>
        [NonAction]
        public async Task UpdateEmployeesAsync(EmployeesEntity model)
        {
            var entity = await GetEmployeesInfoAsync(e => e.Id == model.Id);
            if (entity!=null)
            {
                entity = model.Mapper(entity);
                //保存员工信息到sqlserver
                await _employeesRepository.Context.Updateable(entity).ExecuteCommandAsync();
                //保存员工信息到mongodb
                await _employeesMongoDbRepository.UpdateAsync(entity, _employees, m => m.Id == entity.Id);
            }
            else
            {
                await AddEmployeesAsync(model);
            }
        }

        /// <summary>
        /// 删除员工
        /// </summary>
        /// <param name="id">员工id</param>
        /// <returns></returns>
        [NonAction]
        public async Task DeleteEmployeesAsync(string id)
        {
            var entity = await GetEmployeesInfoAsync(e => e.Id ==id);
            if (entity != null)
            {
                //从sqlserver中删除员工信息
                await _employeesRepository.Context.Deleteable(entity).ExecuteCommandAsync();
                //从mongodb中删除员工信息
                await _employeesMongoDbRepository.DeleteAsync(_employees, m => m.Id == id);
            }
        }
        #endregion

    }
}
